#pragma once
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <pthread.h>
#include "Socket.hpp"

#include "Log.hpp"
extern Log lg;

static const int defaultport = 8081;

const std::string wwwroot="./wwwroot"; 
const std::string homepage = "index.html";
const std::string sep = "\r\n";

class HttpRequest
{
public:
    void Deseriailize(std::string req)
    {
        while(true)
        {
            std::size_t pos = req.find(sep);
            if(pos == std::string::npos) break;

            std::string temp = req.substr(0, pos);
            if(temp.empty()) break;
            req_header.push_back(temp);
            req.erase(0, pos+sep.size());
        }
        text = req;
    }

    void Parse()
    {
        std::stringstream ss(req_header[0]);
        ss >> method >> url >> http_version;
        file_path = wwwroot; 
        if(url == "/" || url == "/index.html") 
        {
            file_path += '/';
            file_path += homepage; // ./wwwroot/index.html
        }
        else
        {
            file_path += url; // ./wwwroot/a/b/c.html
        }
    }

    void DebugPrint()
    {
        for(auto &line : req_header)
        {
            std::cout << "-------------------------------" << std::endl;
            std::cout << line << "\n\n";
        }

        std::cout << "method:" << method << std::endl;
        std::cout << "url: " << url << std::endl;
        std::cout << "http_version: "<< http_version << std::endl;
        std::cout << "text: " << text << std::endl;

    }

public:
    std::vector<std::string> req_header; // 存储报头信息
    std::string text;                    // 存储正文信息

    //解析之后的结果
    std::string method;
    std::string url;
    std::string http_version;
    std::string file_path;
};

// 便于创造线程后传入 sockfd 
class ThreadData
{
public:
    ThreadData(int fd = -1) 
        :sockfd(fd)
    {}

public:
    int sockfd;
};

class HttpServer
{
public:
    HttpServer(uint16_t port = defaultport) 
        :port_(port)
    {}

    bool Start()
    {
        listensock_.Socket();
        listensock_.Bind(port_);
        listensock_.Listen();

        for(;;)
        {
            std::string clientip;
            uint16_t clientport;

            int sockfd = listensock_.Accept(&clientip, &clientport);
            if (sockfd < 0) continue;

            lg(Info, "get a new link, clientip: %s, clientport: %d, sockfd: %d", clientip.c_str(), clientport, sockfd);

            // 创造线程来完成完成 HTTP 服务
            pthread_t tid;
            ThreadData *td = new ThreadData(sockfd);
            pthread_create(&tid, nullptr, ThreadRun, td);
        }
    }

    static std::string ReadHtmlContent(const std::string &htmlpath)
    {
        std::ifstream in(htmlpath);
        if(!in.is_open()) return "";

        std::string content;
        std::string line;
        while(std::getline(in, line))
        {
            content += line;
        }

        in.close();

        return content;
    }

    static void HandlerHttp(int sockfd)
    {
        // 创造缓冲区，读取 HTTP 请求
        char buffer[10240];
        ssize_t n = recv(sockfd, buffer, sizeof(buffer)-1, 0);
        if(n > 0)
        {
            // 假设每次读取都是一个完整报文
            buffer[n] = 0;
            std::cout << buffer;
            HttpRequest req;
            req.Deseriailize(buffer);
            req.Parse();

            // 返回响应

            std::string text;
            bool ok = true;
            text = ReadHtmlContent(req.file_path);
            if(text.empty())
            {
                ok = false;
                std::string err_html = wwwroot;
                err_html += "/";
                err_html += "err.html";
                text = ReadHtmlContent(err_html);
            }

            std::string response_line;
            if(ok)
                response_line = "HTTP/1.0 200 OK\r\n";
            else
                response_line = "HTTP/1.0 404 Not Found\r\n";

            response_line = "HTTP/1.0 302 Redirect\r\n";
            
            // 构建响应报头
            std::string response_header = "content-Length: ";
            response_header += std::to_string(text.size()); // Content-Length: 11
            response_header += "\r\n";
            response_header += "Location: https://www.qq.com/\r\n";

            // 空行
            std::string blank_line = "\r\n"; 

            // 构建响应报文并返回
            std::string response = response_line;
            response += response_header;
            response += blank_line;
            response += text;

            send(sockfd, response.c_str(), response.size(), 0);
        }    
            
        
        close(sockfd);
    }


    static void *ThreadRun(void *args)
    {
        pthread_detach(pthread_self());

        ThreadData *td = static_cast<ThreadData*>(args);

        HandlerHttp(td->sockfd);
        
        delete td;
        return nullptr;
    }

    ~HttpServer(){}
private:
    Sock listensock_;
    uint16_t port_;
};
